package org.acghub.mtdb.common;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * @author zhouhe
 */
public final class Verify {

    private final static Pattern pattern = Pattern.compile("[_a-zA-Z][_a-zA-Z0-9]*");
    private final static Set<String> keywords = new HashSet<>(Arrays.asList("object", "abstract", "add", "alias", "and",
            "and_eq", "as", "ascending", "asm", "assert", "async", "auto", "await", "base", "bitand", "bitor", "bool",
            "boolean", "break", "byte", "case", "catch", "char", "checked", "class", "compl", "const", "const_cast",
            "continue", "decimal", "default", "delegate", "delete", "descending", "do", "double", "dynamic",
            "dynamic_cast", "else", "enum", "event", "explicit", "export", "extends", "extern", "false", "final",
            "finally", "fixed", "float", "for", "foreach", "friend", "get", "global", "goto", "group", "if",
            "implements", "implicit", "import", "in", "inline", "instanceof", "int", "interface", "internal", "into",
            "is", "join", "let", "lock", "long", "mutable", "namespace", "native", "new", "not", "not_eq", "null",
            "object", "operator", "or", "or_eq", "orderby", "out", "override", "package", "params", "partial",
            "private", "protected", "public", "readonly", "ref", "register", "reinterpret_cast", "remove", "return",
            "sbyte", "sealed", "select", "set", "short", "signed", "sizeof", "stackalloc", "static", "static_cast",
            "strictfp", "string", "struct", "super", "switch", "synchronized", "template", "this", "throw", "throws",
            "transient", "true", "try", "typedef", "typeid", "typename", "typeof", "uint", "ulong", "unchecked",
            "union", "unsafe", "unsigned", "ushort", "using", "value", "var", "virtual", "void", "volatile", "wchar_t",
            "where", "while", "xor", "xor_eq", "yield",

            "marshal", "unmarshal", "trace", "encode", "getType", "process", "destroy", "equals", "equals"

    ));

    private static void verifyName(String name) {
        if (!pattern.matcher(name).matches()) {
            throw new RuntimeException("invalid name \"" + name + "\"");
        }
        if (keywords.contains(name.toLowerCase())) {
            throw new RuntimeException("variable reserved keyword \"" + name + "\"");
        }
    }

    public static void verifyName(VerifyType verifyType, String name) {
        switch (verifyType) {
            case TABLE -> {
                if (name.isEmpty()) {
                    throw new RuntimeException("table name MUST NOT empty");
                }
                if (!name.toLowerCase().equals(name)) {
                    throw new RuntimeException("table name MUST BE lowercase");
                }
                if ("_Meta_".equalsIgnoreCase(name)) {
                    throw new RuntimeException("Table name \"" + name + "\" is not permitted.");
                }
                if ("_Tables_".equalsIgnoreCase(name)) {
                    throw new RuntimeException("Table name \"" + name + "\" is not permitted.");
                }
                verifyName(name);
            }

            case BEAN -> {
                if (name.isEmpty()) {
                    throw new RuntimeException("bean name MUST NOT empty");
                }
                if ("bean".equalsIgnoreCase(name)) {
                    throw new RuntimeException("bean name \"" + name + "\" is not permitted.");
                }
                verifyName(name);
            }
            case VAR -> {
                if (name.isEmpty()) {
                    throw new RuntimeException("var name MUST NOT empty");
                }
                verifyName(name);
            }
        }
    }


    public enum VerifyType {
        TABLE,

        BEAN,

        VAR,
    }

}
